package com.bjpowernode.pmes.web.controller;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.bjpowernode.pmes.bean.Processes;
import com.bjpowernode.pmes.bean.Result;
import com.bjpowernode.pmes.common.BaseController;

@Controller
@RequestMapping("/proc")
public class ProcessController extends BaseController {

	@Resource
	private RepositoryService repositoryService;
	@Resource
	private HistoryService historyService;
	@Resource
	private RuntimeService runtimeService;
	@Resource
	private TaskService taskService;
	@Resource
	private SpringProcessEngineConfiguration processEngineConfiguration;
	/**
	 * 输出流程实例监控图形
	 * @param id
	 * @param resp
	 * @throws Exception
	 */
	@RequestMapping("/loadMonitorImg")
	public void loadMonitorImg( String id, HttpServletResponse resp ) throws Exception {
		
		ProcessInstance pi = 
			runtimeService
			    .createProcessInstanceQuery()
			    .processInstanceId(id)
			    .singleResult();
		
		BpmnModel model = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
		
		Context.setProcessEngineConfiguration(processEngineConfiguration);
		
		InputStream in = ProcessDiagramGenerator.generateDiagram(model, "png", runtimeService.getActiveActivityIds(id));
		
		outData(in, resp.getOutputStream());
	}
	
	/**
	 * 输出流程定义图形
	 * @param id
	 * @param resp
	 * @throws Exception
	 */
	@RequestMapping("/loadImg")
	public void loadImg(String id, HttpServletResponse resp) throws Exception {
		
		// 获取流程定义图形
		ProcessDefinition pd =
				repositoryService
				    .createProcessDefinitionQuery()
				    .processDefinitionId(id)
				    .singleResult();
		
		String imgName = pd.getDiagramResourceName();
		String deployId = pd.getDeploymentId();
		
		InputStream in = repositoryService.getResourceAsStream(deployId, imgName);
		OutputStream out = resp.getOutputStream();
		
		// 输出到浏览器中
		outData(in, out);
	}
	
	/**
	 * 跳转到流程定义查看图片的页面
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/view")
	public String view() throws Exception {
		return "proc/view";
	}
	
	/**
	 * 删除选择的流程定义信息
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/deleteProcDefs")
	public Object deleteProcDefs( Processes proc ) throws Exception {
		
		Result r = new Result();
		
		try {
			for ( String pdid : proc.getPdids() ) {
				ProcessDefinition pd =
					repositoryService
					    .createProcessDefinitionQuery()
					    .processDefinitionId(pdid)
					    .singleResult();
				repositoryService.deleteDeployment(pd.getDeploymentId(), true);
			}
			
			r.setSuccess(true);
		} catch ( Exception e ) {
			e.printStackTrace();
			r.setSuccess(false);
		}
		
		return r;
	}
	
	/**
	 * 分页查询流程实例信息
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/pageQueryForPI")
	public Object pageQueryForPI(@RequestParam("page")Integer pageno, @RequestParam("rows")Integer pagesize) throws Exception {
		
		HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
		
		List<HistoricProcessInstance> hpiList = query.listPage((pageno-1)*pagesize, pagesize);
		List<Map<String, Object>> piMapList = new ArrayList<Map<String, Object>>();
		
		for ( HistoricProcessInstance hpi : hpiList ) {
			Map<String, Object> piMap = new HashMap<String, Object>();
			
			piMap.put("id", hpi.getId());
			piMap.put("piid", hpi.getId());
			
			String pdid = hpi.getProcessDefinitionId();
			ProcessDefinition pd =
				repositoryService
				    .createProcessDefinitionQuery()
				    .processDefinitionId(pdid)
				    .singleResult();
			
			piMap.put("pdname", pd.getName());
			
			ProcessInstance pi =
				runtimeService
				    .createProcessInstanceQuery()
				    .processInstanceId(hpi.getId())
				    .singleResult();
			
			if ( pi == null ) {
				piMap.put("actname","无");
				piMap.put("status", "运行完毕");
			} else {
				
				String actId = pi.getActivityId();
				
				Task task =
					taskService
					    .createTaskQuery()
					    .processInstanceId(hpi.getId())
					    .taskDefinitionKey(actId)
					    .singleResult();
				
				piMap.put("actname", task.getName());
				piMap.put("status", "运行中");
			}

			piMapList.add(piMap);
		}
		
		// 查询流程定义数量
		long cnt = query.count();
		
		Map<String, Object> resultMap = new HashMap<String, Object>();
		
		resultMap.put("total", cnt);
		resultMap.put("rows", piMapList);
		
		return resultMap;
	}
	
	/**
	 * 分页查询流程定义信息
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/pageQuery")
 	public Object pageQuery( @RequestParam("page")Integer pageno, @RequestParam("rows")Integer pagesize ) throws Exception {
	 
		ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
		// 查询流程定义集合数据
		List<ProcessDefinition> list = query.listPage((pageno-1)*pagesize, pagesize);
		List<Map<String, Object>> pdMapList = new ArrayList<Map<String, Object>>();
		
		for ( ProcessDefinition pd : list ) {
			Map<String, Object> pdMap = new HashMap<String, Object>();
			
			pdMap.put("id", pd.getId());
			pdMap.put("key", pd.getKey());
			pdMap.put("name", pd.getName());
			pdMap.put("version", pd.getVersion());
			
			pdMapList.add(pdMap);
		}
		
		// 查询流程定义数量
		long cnt = query.count();
		
		Map<String, Object> resultMap = new HashMap<String, Object>();
		
		resultMap.put("total", cnt);
		resultMap.put("rows", pdMapList);
		
		return resultMap;
	}
	
	/**
	 * 上传流程定义文件
	 * @return
	 * @throws Excetpion
	 */
	@RequestMapping("/upload")
	public String upload( @RequestParam("procDefFile")MultipartFile file ) throws Exception {
		
		// 将上传的流程定义文件部署到流程框架中
		repositoryService
		    .createDeployment()
		    .addInputStream(file.getOriginalFilename(), file.getInputStream())
		    .deploy();
		
		return "redirect:/proc/index.do";
	}
	
	/**
	 * 跳转到流程分页查询页面
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/index")
	public String index() throws Exception {
		return "proc/index";
	}
	
	/**
	 * 跳转到流程监控分页查询页面
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/monitor")
	public String monitor() throws Exception {
		return "proc/monitor";
	}
	
	/**
	 * 跳转到新增流程定义页面
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/add")
	public String add() throws Exception {
		return "proc/add";
	}
}
